﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using snat.model;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Data;
using System.IO;

namespace snat.algorithms.network.TFIDF {

    public class TFIDFMonitor<T> : IAlgorithm where T : Document{

        Dictionary<String, Term> Terms = new Dictionary<String, Term>();
        List<T> Documents = new List<T>();

        public TFIDFMonitor() {
        }

        public void OnMessage(Message m) {
            //create the document using dirty reflection
            T document = (T)Activator.CreateInstance(
                    typeof(T),
                    new object[] { m, Terms, true });
            Documents.Add(document);
            Console.WriteLine(Documents.Count);
        }

        public void Analyze() {
            Console.WriteLine("We have " + Documents.Count + " documents");
    
            
            Console.Write("Populating IDF values...");
            Parallel.ForEach<Term>(Terms.Values,
                term => { term.IDF = Math.Log((double)Documents.Count / (double)term.AppearenceCount); });
            Console.Write("done.\nPopulating IDF values...");
            Dictionary<Term, double> termsDict = Terms.Values.ToDictionary(e => e, e => e.IDF);
            Parallel.ForEach<Document>(Documents,
                document => { document.PopulateTFIDF(termsDict); });
            Console.WriteLine("done.");

            List<T> mostImportantDocuments = Documents.OrderByDescending(e => e.DocumentImportance).ToList().GetRange(0, 20);
            Console.WriteLine("\n\n\nWord in most important documents");
            foreach (Document d in mostImportantDocuments) {
                Console.WriteLine(NetworkModel.Instance.Nodes[d.Sender.ID]+"  Document: "+d.ID + ", Importance = " + d.DocumentImportance);
                int count = 0;
                foreach (Term t in d.tfidf.Keys.OrderByDescending(e => e.IDF)) {
                    Console.WriteLine(t.word+" : Appearences = "+t.AppearenceCount+", tfidf = "+d.tfidf[t]);
                    if (count++ == 5) break;
                }
                Console.WriteLine("-----------");
            }
        }

        public string Name {
            get { return "TFIDF"; }
        }

        public void Register() {
            NetworkModel.Instance.MessageProcessed += OnMessage;
            NetworkModel.Instance.TapePaused += Analyze;
            NetworkModel.Instance.TapeEnded += Analyze;
        }

        public void DeRegister() {
            NetworkModel.Instance.MessageProcessed -= OnMessage;
            NetworkModel.Instance.TapePaused -= Analyze;
            NetworkModel.Instance.TapeEnded -= Analyze;
        }
    }
}